package com.afalon.cloud.rest.finance;

import java.net.URI;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo;

import com.afalon.cloud.PMF;
import com.afalon.cloud.Session;
import com.afalon.cloud.contracts.finance.Account;
import com.afalon.cloud.contracts.finance.Chart;
import com.afalon.cloud.contracts.system.User;
import com.afalon.cloud.rest.system.RestSystem;
import com.google.appengine.api.datastore.KeyFactory;
import com.sun.jersey.api.JResponse;

@Path("/finance")
public class RestFinance {

	@GET
	@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	@Path("/charts/{chartid}")
	public JResponse<Chart> getChart(
			@PathParam("chartid") String chartId,
			@Context HttpServletRequest request,
			@Context UriInfo uriInfo) {
		Session.Authenticated(request);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			Chart chart = pm.getObjectById(Chart.class, chartId);
			if (chart == null) {
				throw new WebApplicationException(Response
						.status(Response.Status.NOT_FOUND)
						.entity("No results.").type(MediaType.TEXT_PLAIN)
						.build());
			} else {
				chart.chartUri = UriBuilder.fromUri(uriInfo.getBaseUri()).path("finance/charts").path(chart.getChartId()).build();
				return JResponse.ok(chart).build();
			}
		} finally {
			pm.close();
		}
	}
	
	@GET
	@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	@Path("/charts")
	public JResponse<List<Chart>> getCharts(
			@QueryParam("name") String name,
			@Context HttpServletRequest request,
			@Context UriInfo uriInfo) {
		Session.Authenticated(request);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery(Chart.class);
		if (name != null) {
			query.setFilter("name == '" + name + "'");
		}
		try {
			@SuppressWarnings("unchecked")
			List<Chart> charts = (List<Chart>) query.execute();
			if (charts.iterator().hasNext()) {
				for (Chart chart : charts) {
					chart.chartUri = UriBuilder.fromUri(uriInfo.getBaseUri()).path("finance/charts").path(chart.getChartId()).build();
				}
				return JResponse.ok(charts).build();
			} else {
				throw new WebApplicationException(Response
						.status(Response.Status.NOT_FOUND)
						.entity("No results.").type(MediaType.TEXT_PLAIN)
						.build());
			}
		} finally {
			query.closeAll();
		}
	}
	
	@POST
	@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	@Path("/charts")
	public Response postChart(
			Chart chart,
			@Context HttpServletRequest request) {
		Session.Authenticated(request);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			pm.makePersistent(chart);
			return Response.created(
					URI.create(KeyFactory.keyToString(chart.getChartKey())))
					.build();
		} finally {
			pm.close();
		}
	}

	@PUT
	@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	@Path("/charts/{chartid}")
	public Response putChart(
			Chart chart,
			@PathParam("chartid") String chartId,
			@Context HttpServletRequest req,
			@Context UriInfo uriInfo) {
		Session.Authenticated(req);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			Chart chartResult = pm.getObjectById(Chart.class, chartId);
			if (chartResult == null) {
				throw new WebApplicationException(Response
						.status(Response.Status.NOT_FOUND)
						.entity("No results.").type(MediaType.TEXT_PLAIN)
						.build());
			} else {
				if (chart.getName()!=null && !chart.getName().isEmpty() && chart.getName()!=chartResult.getName()) {
					chartResult.setName(chart.getName());
				}
				pm.makePersistent(chartResult);
				chartResult.chartUri = UriBuilder.fromUri(uriInfo.getBaseUri()).path("finance/charts").path(chartResult.getChartId()).build();
				return Response.noContent().build();
			}
		} finally {
			pm.close();
		}
	}

	@DELETE
	@Path("/charts/{chartid}")
	public Response deleteChart(
			@PathParam("chartid") String chartId,
			@Context HttpServletRequest request) {
		Session.Authenticated(request);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			Chart chart = pm.getObjectById(Chart.class, chartId);
			if (chart == null) {
				throw new WebApplicationException(Response
						.status(Response.Status.NOT_FOUND)
						.entity("No results.").type(MediaType.TEXT_PLAIN)
						.build());
			} else {
				pm.deletePersistent(chart);
				return Response.noContent().build();
			}
		} finally {
			pm.close();
		}
	}

	// ACCOUNTS
	
	// POST (Create) Account
	@POST
	@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	@Path("/charts/{chartid}/accounts")
	public Response postAccount(Account account,
			@PathParam("chartid") String chartId,
			@Context HttpServletRequest request) {
		Session.Authenticated(request);
		PersistenceManager pm = PMF.get().getPersistenceManager();

		try {
			Chart chart = pm.getObjectById(Chart.class, chartId);
			chart.getAccounts().add(account);
			pm.makePersistent(chart);
			pm.makePersistent(account);
			return Response.created(
					URI.create(KeyFactory.keyToString(account.getAccountKey())))
					.build();
		} finally {
			pm.close();
		}

	}

	// GET (Read) Account (by Id)
	@GET
	@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	@Path("/charts/{chartid}/accounts/{accountid}")
	public JResponse<Account> getAccount(
			@PathParam("chartid") String chartId,
			@PathParam("accountid") String accountId,
			@Context HttpServletRequest request,
			@Context UriInfo uriInfo) {
		Session.Authenticated(request);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			Account account = pm.getObjectById(Account.class, accountId);
			if (account == null) {
				throw new WebApplicationException(Response
						.status(Response.Status.NOT_FOUND)
						.entity("No results.").type(MediaType.TEXT_PLAIN)
						.build());
			} else {
				return JResponse.ok(account).build();
			}
		} finally {
		}
	}

	// GET (Read) Accounts
	@GET
	@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	@Path("/charts/{chartid}/accounts")
	public JResponse<List<Account>> getAccounts(
			@PathParam("chartid") String chartId,
			@Context HttpServletRequest request,
			@Context UriInfo uriInfo) {
		Session.Authenticated(request);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		Query query = pm.newQuery(Account.class);
		try {
			Chart chart = pm.getObjectById(Chart.class, chartId);
			if (chart.getAccounts().iterator().hasNext()) {
				return JResponse.ok(chart.getAccounts()).build();
			} else {
				throw new WebApplicationException(Response
						.status(Response.Status.NOT_FOUND)
						.entity("No results.").type(MediaType.TEXT_PLAIN)
						.build());
			}
		} finally {
			query.closeAll();
		}
	}

	// PUT (Update) Account
	@PUT
	@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
	@Path("/charts/{chartid}/accounts/{accountid}")
	public Response putAccount(Account account,
			@PathParam("chartid") String chartId,
			@PathParam("accountid") String accountId,
			@Context HttpServletRequest req) {
		Session.Authenticated(req);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			Account accountResult = pm.getObjectById(Account.class, accountId);
			if (accountResult == null) {
				throw new WebApplicationException(Response
						.status(Response.Status.NOT_FOUND)
						.entity("No results.").type(MediaType.TEXT_PLAIN)
						.build());
			} else {
				accountResult.setName(account.getName());
				accountResult.setType(account.getType());
				accountResult.setGroup(account.getGroup());
				return Response.noContent().build();
			}
		} finally {
			pm.close();
		}
	}

	// DELETE (Delete) Account (by Id)
	@DELETE
	@Path("/charts/{chartid}/accounts/{accountid}")
	public Response deleteAccount(
			@PathParam("accountid") String accountId,
			@Context HttpServletRequest request) {
		Session.Authenticated(request);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			Account account = pm.getObjectById(Account.class, accountId);
			if (account == null) {
				throw new WebApplicationException(Response
						.status(Response.Status.NOT_FOUND)
						.entity("No results.").type(MediaType.TEXT_PLAIN)
						.build());
			} else {
				pm.deletePersistent(account);
				return Response.noContent().build();
			}
		} finally {
			pm.close();
		}
	}

	
}
